home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <nslib.h>
- #include <pc_inc.h>
-
- #define BITS (14)
- #define BITS_ (9)
- #define MAX_CODE ( 16383 )
- #define TABLE_SIZE ( 20011 )
- #define BUMP_CODE ( 256 )
- #define EOS ( 257 )
- #define FIRST_CODE ( 258 )
- #define UNUSED ( -1 )
-
- static char *stack;
- static DIC *dic;
-
-
- static int find_child_node( short parent, short child )
- {
- short idx, offset;
-
- idx = ( child << ( BITS - 8 ) ) ^ parent;
- if ( idx == 0 )
- offset = 1;
- else
- offset = TABLE_SIZE - idx;
- for ( ; ; )
- {
- if ( dic[idx].code == UNUSED )
- return( idx );
- if ( dic[idx].parent == parent && dic[idx].ch == (char)child )
- return( idx );
- idx -= offset;
- if ( idx < 0 )
- idx += TABLE_SIZE;
- }
- }
-
- static int decode_string( int cu, short code )
- {
- while ( code > 255 )
- {
- stack[cu++] = dic[code].ch;
- code = dic[code].parent;
- }
- stack[cu++] = (char)code;
- return( cu );
- }
-
- int lzw_comp( char *src, int n, BIT_FILE *bfp )
- {
- short ch, str, next=FIRST_CODE;
- int i, idx, bits=BITS_, bump=512, si=0, ret=0;
-
- if ( ( dic = malloc( sizeof(DIC)*TABLE_SIZE ) ) == NULL )
- return (-1);
-
- for ( i=0; i<TABLE_SIZE; i++ )
- dic[i].code = UNUSED;
- str = (short)src[si++];
-
- while ( si < n )
- {
- ch = (short)src[si++];
- idx = find_child_node( str, ch );
- if ( dic[idx].code != UNUSED )
- str = dic[idx].code;
- else
- {
- if ( next <= MAX_CODE )
- {
- dic[idx].code = next++;
- dic[idx].parent = str;
- dic[idx].ch = (char)ch;
- }
- if ( BIT_write_bits( str, bits, bfp ) < bits )
- goto err;
- ret += bits;
- if ( next >= bump )
- {
- if ( BIT_write_bits( BUMP_CODE, bits, bfp ) < bits )
- goto err;
- ret += bits;
- bits++;
- bump <<= 1;
- }
- str = ch;
- }
- }
- if ( BIT_write_bits( str, bits, bfp ) < bits ) goto err;
- if ( BIT_write_bits( EOS, bits, bfp ) < bits ) goto err;
- ret += bits*2;
-
- free( dic );
- return ( ret );
-
- err:free( dic );
- return (-1);
- }
-
- int lzw_exp( char *dest, BIT_FILE *bfp )
- {
- short ch, new, old, next=FIRST_CODE;
- int count, di=0, bits=BITS_;
- unsigned int ret;
-
- if ( ( dic = malloc( sizeof(DIC)*TABLE_SIZE ) ) == NULL )
- return (0);
- if ( ( stack = malloc( TABLE_SIZE ) ) == NULL )
- { free( dic ); return (0); }
-
- if ( BIT_read_bits( &ret, bits, bfp ) < bits )
- goto end;
- old = (short)ret;
- ch = old;
- dest[di++] = (char)old;
-
- for( ; ; )
- {
- if ( BIT_read_bits( &ret, bits, bfp ) < bits )
- break;
- if ( ( new = (short)ret ) == EOS ) break;
- else if ( new == BUMP_CODE )
- {
- bits++;
- continue;
- }
- else if ( new >= next )
- {
- stack[0] = (char)ch;
- count = decode_string( 1, old );
- }
- else
- count = decode_string( 0, new );
- ch = stack[count-1];
- while ( count > 0 )
- dest[di++] = (char)stack[--count];
- if ( next <= MAX_CODE )
- {
- dic[next].parent = old;
- dic[next].ch = (char)ch;
- next++;
- }
- old = new;
- }
-
- end:free( dic );
- free( stack );
- return ( di );
- }
-